package org.flashbrighton.as3bots.controllers
{
	import Box2D.Collision.*;
	import Box2D.Common.Math.*;
	import Box2D.Dynamics.*;
	import Box2D.Dynamics.Contacts.*;
	
	import flash.events.*;
	
	import org.flashbrighton.as3bots.events.*;
	import org.flashbrighton.as3bots.models.*;
	import org.flashbrighton.as3bots.utils.MathUtils;
	import org.flashbrighton.as3bots.views.ui.Message;
	
	
	public class CollisionScorer extends EventDispatcher implements IContactListener
	{
		public static var GEM_BONUS:int = 20;
		public static var MAX_DAMAGE:int = -50;
		
		private var _botModel1:BotModel;
		private var _botModel2:BotModel;
		private var _gemModel:GemModel;
		private var _bombModel:BombModel;
		private var _hitPos1:Number;
		private var _hitPos2:Number;
		private var _health1:Number;
		private var _health2:Number;
		private static const _PI:Number= Math.PI;
		private static const _2PI:Number = Math.PI*2;
		private var _type:String;
		
		
		public function CollisionScorer()
		{			
		}
		
		
		public function BeginContact(contact:b2Contact):void { }
		public function EndContact(contact:b2Contact):void { }
		public function PreSolve(contact:b2Contact, oldManifold:b2Manifold):void { }
		
		
		public function PostSolve(contact:b2Contact, impulse:b2ContactImpulse):void
		{
			var manifold:b2WorldManifold = new b2WorldManifold();
			contact.GetWorldManifold(manifold);
			calculate(manifold.m_points[0], impulse, contact.GetFixtureA().GetBody(), contact.GetFixtureB().GetBody());
			if (impulse.normalImpulses[0] > 0) notify();
		}
		
		
		public function calculate(point:b2Vec2, impulse:b2ContactImpulse, bodyA:b2Body, bodyB:b2Body):void
		{
			var impulseNormal:Number = impulse.normalImpulses[0] / 10;			
			
			_botModel1 = bodyA.GetUserData() as BotModel;
			_botModel2 = bodyB.GetUserData() as BotModel;
					
			if (!_botModel1 && !_botModel2) return; //ignore wall-wall collisions
			
			_health1 = 0;
			_health2 = 0;
			// Ignore persistant collisions			
			//if (impulseNormal < 0.8) maxHitScore = 0;
			if (_botModel1!=null && bodyB.GetUserData() is BombModel){
				_bombModel = bodyB.GetUserData() as BombModel;
				_type = CollidableType.BOMB;
				_hitPos1 = MathUtils.getDirection(_botModel1, point.x, point.y);
				_health1 = -_bombModel.damage;
			}
			else if (_botModel2!=null && bodyA.GetUserData() is BombModel)
			{
				_bombModel = bodyA.GetUserData() as BombModel;
				_type = CollidableType.BOMB; 
				_hitPos2 = MathUtils.getDirection(_botModel2, point.x, point.y);
				_health2 = -_bombModel.damage;
			}
			else if (_botModel1!=null && bodyB.GetUserData() is GemModel)
			{
				_type = CollidableType.GEM;
				_gemModel = bodyB.GetUserData() as GemModel;
				_hitPos1 = MathUtils.getDirection(_botModel1, point.x, point.y);
				_health1 = _gemModel.bonus;
			}
			else if (_botModel2!=null && bodyA.GetUserData() is GemModel)
			{
				_type = CollidableType.GEM;
				_gemModel = bodyA.GetUserData() as GemModel;
				_hitPos2 = MathUtils.getDirection(_botModel2, point.x, point.y);
				_health2 = _gemModel.bonus;
				
			}else if (_botModel1)
			{
				if(_botModel2 == null){
					Message.write(null, "bug!!");
				}
				_type = CollidableType.BOT;

				_hitPos1 = MathUtils.getDirection(_botModel1, point.x, point.y);
				_hitPos2 = MathUtils.getDirection(_botModel2, point.x, point.y);
				
				_health1 = Math.round(Math.abs(hitPos1) * MAX_DAMAGE * impulseNormal);
				_health2 = Math.round(Math.abs(hitPos2) * MAX_DAMAGE * impulseNormal);
			}
			else
			{
				_type = CollidableType.WALL;
				
				_hitPos2 = MathUtils.getDirection(_botModel2, point.x, point.y);								
				_health2 = Math.round(Math.abs(_hitPos2) * MAX_DAMAGE * impulseNormal);
			}
 		}
		
		
		public function notify():void
		{
			if (_botModel1)
			{
				var evt1:CollisionEvent = new CollisionEvent(BotEvent.HIT, _botModel1, _hitPos1, _health1, _type);
				if(_type == CollidableType.GEM){
					evt1.gem = _gemModel;
				}else if(_type == CollidableType.BOMB){
					evt1.bomb = _bombModel;
				}
				dispatchEvent(evt1);
				_botModel1 = null;
			}
			
			if (_botModel2)
			{
				var evt2:CollisionEvent = new CollisionEvent(BotEvent.HIT, _botModel2, _hitPos2, _health2, _type);
				if(_type == CollidableType.GEM){
					evt2.gem = _gemModel;
				}else if(_type == CollidableType.BOMB){
					evt2.bomb = _bombModel;
				}
				dispatchEvent(evt2);
				_botModel2 = null;
			}
		}
 		
 		
 		public function get hitPos1():Number
 		{
 			return _hitPos1;
 		}
 		
 		
 		public function get hitPos2():Number
 		{
 			return _hitPos2;
 		}
 		
 		
 		public function get health1():Number
 		{
 			return _health1;
 		}
 		
 		
 		public function get health2():Number
 		{
 			return _health2;
 		}
 		
	}
}